function DoublyLinkedList() {
  function LinkedElement(data) {
    this.prev = null;
    this.next = null;
    this.data = data;
  }

  this.head = null;
  this.tail = null;
  this.length = 0;

  DoublyLinkedList.prototype.append = function (data) {
    const el = new LinkedElement(data);

    if (this.length == 0) {
      this.head = el;
      this.tail = el;
    } else {
      let current = this.head;
      while (current.next) {
        current = current.next;
      }
      current.next = el;
      el.prev = current;
      this.tail = el;
    }
    this.length += 1;
    return this;
  };

  DoublyLinkedList.prototype.insert = function (position, data) {
    if (position < 0 || position > this.length) {
      return false;
    }
    const newNode = new LinkedElement(data);
    if (position == 0) {
      newNode.next = this.head;
      this.head.prev = newNode;
      this.head = newNode;
    } else if (position == this.length) {
      newNode.prev = this.tail;
      this.tail.next = newNode;
      this.tail = newNode;
    } else {
      let current = this.head;
      let prev = null;
      let idx = 0;
      while (idx++ < position) {
        current = current.next;
      }
      prev = current.prev;
      current.prev = newNode;
      newNode.next = current;
      newNode.prev = prev;
      prev.next = newNode;

      this.length += 1;
    }
  };

  DoublyLinkedList.prototype.get = function (position) {
    if (position < 0 || position >= this.length) return null;
    let current;
    let idx;

    if (position < this.length / 2) {
      idx = 0;
      current = this.head;
      while (idx++ < position) {
        current = current.next;
      }
    } else {
      current = this.tail;
      idx = this.length - 1;
      while (idx-- > position) {
        current = current.prev;
      }
    }

    return current.data;
  };

  DoublyLinkedList.prototype.indexOf = function (data) {
    let idx = 0;
    let current = this.head;
    while (current) {
      if (current.data == data) {
        return idx;
      }
      idx++;
      current = current.next;
    }
    return -1;
  };

  DoublyLinkedList.prototype.update = function (position, data) {
    if (position < 0 || position >= this.length) return false;
    let current;
    let idx;
    // const newNode = new LinkedElement(data);
    if (position < this.length / 2) {
      idx = 0;
      current = this.head;
      while (idx++ < position) {
        current = current.next;
      }
    } else {
      current = this.tail;
      idx = this.length - 1;
      while (idx-- > position) {
        current = current.prev;
      }
    }
    current.data = data;
    return true;
  };

  DoublyLinkedList.prototype.removeAt = function (position) {
    if (position < 0 || position >= this.length) return false;
    let current = this.head;
    let idx = 0;
    let data;
    // const newNode = new LinkedElement(data);
    if (this.length == 1) {
      data = this.head.data;
      this.head = null;
      this.tail = null;
    } else if (position == 0) {
      data = this.head.data;
      this.head = this.head.next;
      this.head.prev = null;
    } else if (position == this.length - 1) {
      data = this.tail.data;
      this.tail = this.tail.prev;
      this.tail.next = null;
    } else {
      while (idx++ < position) {
        current = current.next;
      }
      current.prev.next = current.next;
      current.next.prev = current.prev;
      data = current.data;
    }
    this.length -= 1;
    return data;
  };

  DoublyLinkedList.prototype.remove = function (data) {
    let idx = this.indexOf(data);
    return this.removeAt(idx);
  };
  DoublyLinkedList.prototype.forwardString = function () {
    let str = "";
    let current = this.head;
    while (current) {
      str += current.data + " ";
      current = current.next;
    }
    return str;
  };

  DoublyLinkedList.prototype.backwardString = function () {
    let str = "";
    let current = this.tail;
    while (current) {
      str += current.data + " ";
      current = current.prev;
    }
    return str;
  };

  DoublyLinkedList.prototype.isEmpty = function () {
    return this.length == 0;
  };
  DoublyLinkedList.prototype.size = function () {
    return this.length;
  };
}

let a = new DoublyLinkedList();
a.append(1);
a.append(2);
a.insert(1, 3);
console.log(a);
console.log(a.forwardString());
console.log(a.backwardString());
console.log(a.get(2));
console.log(a.indexOf(2));
a.update(2, 11);
console.log(a.forwardString());
console.log(a.removeAt(1));
console.log(a.forwardString());
console.log(a.removeAt(1));
console.log(a.forwardString());
console.log(a.remove(2));
